//go:build windows
// +build windows

package w32

import (
	"unicode/utf16"
	"unsafe"

	"golang.org/x/sys/windows"
	"syscall"
)

var (
	ole32    = windows.NewLazySystemDLL("ole32")
	X初始化线程Ex = ole32.NewProc("CoInitializeEx")

	kernel32  = windows.NewLazySystemDLL("kernel32")
	X获取当前线程ID = kernel32.NewProc("GetCurrentThreadId")

	shlwapi = windows.NewLazySystemDLL("shlwapi")
	X创建内存流  = shlwapi.NewProc("SHCreateMemStream")

	user32     = windows.NewLazySystemDLL("user32")
	X加载图像W     = user32.NewProc("LoadImageW")
	X获取系统参数    = user32.NewProc("GetSystemMetrics")
	X注册窗口类EXW  = user32.NewProc("RegisterClassExW")
	X创建窗口EXW   = user32.NewProc("CreateWindowExW")
	X销毁窗口      = user32.NewProc("DestroyWindow")
	X显示窗口      = user32.NewProc("ShowWindow")
	X设置前台窗口    = user32.NewProc("SetForegroundWindow")
	X更新窗口      = user32.NewProc("UpdateWindow")
	X设置焦点      = user32.NewProc("SetFocus")
	X获取消息W     = user32.NewProc("GetMessageW")
	X翻译消息      = user32.NewProc("TranslateMessage")
	X分发消息W     = user32.NewProc("DispatchMessageW")
	X默认窗口过程W   = user32.NewProc("DefWindowProcW")
	X获取客户区矩形   = user32.NewProc("GetClientRect")
	X发送退出消息    = user32.NewProc("PostQuitMessage")
	X发送异步消息W   = user32.NewProc("PostMessageW")
	X设置窗口文本W   = user32.NewProc("SetWindowTextW")
	X获取窗口长指针W  = user32.NewProc("GetWindowLongPtrW")
	X设置窗口长指针W  = user32.NewProc("SetWindowLongPtrW")
	X调整窗口大小    = user32.NewProc("AdjustWindowRect")
	X设置窗口位置和尺寸 = user32.NewProc("SetWindowPos")
	X是否为对话框消息  = user32.NewProc("IsDialogMessage")
	X获取祖先窗口    = user32.NewProc("GetAncestor")
	X获取窗口客户区矩形 = user32.NewProc("GetWindowRect")
	X发送消息W     = user32.NewProc("SendMessageW")
	X注册热键      = user32.NewProc("RegisterHotKey")
	X注销热键      = user32.NewProc("UnregisterHotKey")
	X系统参数信息W   = user32.NewProc("SystemParametersInfoW")
	X设置分层窗口属性  = user32.NewProc("SetLayeredWindowAttributes")
	X从资源创建图标   = user32.NewProc("CreateIconFromResourceEx")
	X释放鼠标捕获_   = user32.NewProc("ReleaseCapture")
)

const (
	SM_CXSCREEN = 0
	SM_CYSCREEN = 1
)

const (
	CW_USEDEFAULT = 0x80000000
)

const (
	LR_DEFAULTCOLOR     = 0x0000
	LR_MONOCHROME       = 0x0001
	LR_LOADFROMFILE     = 0x0010
	LR_LOADTRANSPARENT  = 0x0020
	LR_DEFAULTSIZE      = 0x0040
	LR_VGACOLOR         = 0x0080
	LR_LOADMAP3DCOLORS  = 0x1000
	LR_CREATEDIBSECTION = 0x2000
	LR_SHARED           = 0x8000
	WS_EX_TOOLWINDOW    = 0x00000080
)

const (
	SystemMetricsCxIcon = 11
	SystemMetricsCyIcon = 12
)

const (
	X常量_显示窗口  = 5
	X常量_最小化窗口 = 6
	X常量_最大化窗口 = 3
	X常量_还原窗口  = 9
	X常量_隐藏窗口  = 0
)

const (
	HWND_TOP       = 0
	HWND_TOPMOST   = -1
	HWND_NOTOPMOST = -2

	SWP_NOMOVE       = 0x0002
	SWP_NOSIZE       = 0x0001
	SWP_SHOWWINDOW   = 0x0040
	SWP_NOZORDER     = 0x0004
	SWP_NOACTIVATE   = 0x0010
	SWP_FRAMECHANGED = 0x0020
)

const (
	X常量_销毁        = 0x0002
	X常量_移动        = 0x0003
	X常量_调整大小      = 0x0005
	X常量_激活        = 0x0006
	X常量_关闭        = 0x0010
	X常量_退出        = 0x0012
	X常量_获取最小最大化信息 = 0x0024
	X常量_左键按下      = 0x00A1
	X常量_移动中       = 0x0216
	X常量_队列函数      = 0x8000
)

const (
	GAParent    = 1
	GARoot      = 2
	GARootOwner = 3
)

const (
	GWLStyle = ^(16 - 1)
)

const (
	X常量_窗口样式_无边框窗口 uint32 = 0x00000000
	X常量_窗口样式_最大化按钮 uint32 = 0x00010000
	X常量_窗口样式_粗边框   uint32 = 0x00040000
	X常量_窗口样式_标题栏   uint32 = 0x00C00000
	X常量_窗口样式_系统菜单  uint32 = 0x00080000
	X常量_窗口样式_最小化按钮 uint32 = 0x00020000
	X常量_窗口样式_普通窗口  uint32 = (X常量_窗口样式_无边框窗口 | X常量_窗口样式_标题栏 | X常量_窗口样式_系统菜单 | X常量_窗口样式_粗边框 | X常量_窗口样式_最小化按钮 | X常量_窗口样式_最大化按钮)
	X常量_窗口样式_弹出窗口  uint32 = 0x80000000
	X常量_窗口样式_窗口可见  uint32 = 0x10000000
)

const (
	WAInactive    = 0
	WAActive      = 1
	WAActiveClick = 2
)

const (
	HTCaption     = 2
	HTLeft        = 10
	HTRight       = 11
	HTTop         = 12
	HTTopLeft     = 13
	HTTopRight    = 14
	HTBottom      = 15
	HTBottomLeft  = 16
	HTBottomRight = 17
)

const (
	WMLButtonDown = 0x0201
	WMNCHitTest   = 0x0084
)

const (
	// Modifiers
	MOD_ALT      = 0x0001
	MOD_CONTROL  = 0x0002
	MOD_SHIFT    = 0x0004
	MOD_WIN      = 0x0008
	MOD_NOREPEAT = 0x4000

	// Messages
	WMHotKey = 0x0312
)

const (
	VK_ESCAPE = 0x1B
	VK_SPACE  = 0x20
	VK_TAB    = 0x09
	VK_F1     = 0x70
	VK_F2     = 0x71
	VK_F3     = 0x72
	VK_F4     = 0x73
	VK_F5     = 0x74
	VK_F6     = 0x75
	VK_F7     = 0x76
	VK_F8     = 0x77
	VK_F9     = 0x78
	VK_F10    = 0x79
	VK_F11    = 0x7A
	VK_F12    = 0x7B
)

const (
	SPI_GETWORKAREA = 0x0030
)

const (
	GWL_EXSTYLE   = -20
	WS_EX_LAYERED = 0x00080000
	LWA_ALPHA     = 0x00000002
	LWA_COLORKEY  = 0x00000001
)

const (
	IMAGE_ICON = 1
)

type X结构_窗口类ExW struct {
	X结构体大小    uint32
	X样式       uint32
	X窗口过程函数指针 uintptr
	X类附加数据    int32
	X窗口附加数据   int32
	X实例句柄     windows.Handle
	X图标句柄     windows.Handle
	X光标句柄     windows.Handle
	X背景画刷句柄   windows.Handle
	X菜单名称     *uint16
	X类名称      *uint16
	X小图标句柄    windows.Handle
}

type X结构_矩形 struct {
	X左 int32
	X上 int32
	X右 int32
	X下 int32
}

type MinMaxInfo struct {
	PtReserved     X结构_坐标
	PtMaxSize      X结构_坐标
	PtMaxPosition  X结构_坐标
	PtMinTrackSize X结构_坐标
	PtMaxTrackSize X结构_坐标
}

type X结构_坐标 struct {
	X, Y int32
}

type X窗口消息 struct {
	X窗口句柄  windows.Handle
	X消息类型  uint32
	X第一个消息 uintptr
	X第二个消息 uintptr
	X时间戳   uint32
	X鼠标位置  X结构_坐标
	X私有数据  uint32
}

type Handle = windows.Handle

// IUnknown COM 接口
type IUnknown struct {
	vtbl *struct {
		QueryInterface uintptr
		AddRef         uintptr
		Release        uintptr
	}
}

func (u *IUnknown) X释放COM对象() uint32 {
	if u == nil || u.vtbl == nil {
		return 0
	}
	ret, _, _ := syscall.Syscall(u.vtbl.Release, 1, uintptr(unsafe.Pointer(u)), 0, 0)
	return uint32(ret)
}

func Utf16文本指针到go文本(p *uint16) string {
	if p == nil {
		return ""
	}
	// Find NUL terminator.
	end := unsafe.Pointer(p)
	n := 0
	for *(*uint16)(end) != 0 {
		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
		n++
	}
	s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
	return string(utf16.Decode(s))
}

func SHCreateMemStream(data []byte) (uintptr, error) {
	ret, _, err := X创建内存流.Call(
		uintptr(unsafe.Pointer(&data[0])),
		uintptr(len(data)),
	)
	if ret == 0 {
		return 0, err
	}

	return ret, nil
}
